package com.aioz.security.service.impl;

import com.aioz.security.common.ResponseResult;
import com.aioz.security.entity.LoginUser;
import com.aioz.security.entity.User;
import com.aioz.security.entity.vo.OnlineUser;
import com.aioz.security.mapper.UserMapper;
import com.aioz.security.service.LoginService;
import com.aioz.security.utils.JwtUtil;
import com.aioz.security.utils.RedisCache;
import io.jsonwebtoken.lang.Strings;
import org.apache.poi.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;


@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserMapper userMapper;


    @Override
    public ResponseResult login(User user) {
        //校验验证码
        String verCode = redisCache.getCacheObject(user.getCaptchaKey());
        if(!Strings.hasText(verCode) || !verCode.equals(user.getVerCode())){
            return new ResponseResult(200,"验证错误");
        }
        // 使用 authenticationManager authenticate 方法校验
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        // 校验失败
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("用户名或密码错误!");
        }
        // 自己生成 jwt 给前端
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        User currentUser = loginUser.getUser();
        String userId = loginUser.getUser().getId().toString();
        String jwt = JwtUtil.createJWT(userId);
        //查询用户是否为企业用户
        Integer companyId = userMapper.getCompanyIdByUserId(Long.valueOf(userId));
        Map<String,Object> map = new HashMap<>();
        if(null != companyId){
            map.put("companyId",companyId);
        }
        map.put("token",jwt);
        map.put("user",currentUser);
        // 系统用户信息存入 redis
        redisCache.setCacheObject("login:"+userId,loginUser);
        OnlineUser onlineUser = new OnlineUser(
                currentUser.getId(),
                currentUser.getUserName(),
                LocalDateTime.now(),
                ""
        );
        redisCache.setCacheSet("online:",onlineUser);
        return new ResponseResult(200,"登录成功",map);
    }

    @Override
    public ResponseResult logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        redisCache.deleteObject("login:"+userId);
        Set<OnlineUser> onlineUsers = redisCache.getCacheSet("online:");
        OnlineUser user = onlineUsers.stream()
                .filter(onlineUser -> Objects.equals(onlineUser.getId(), loginUser.getUser().getId()))
                .collect(Collectors.toList())
                .get(0);
        redisCache.deleteCacheSet("online:",user);
        return new ResponseResult(200,"退出成功!");
    }

    @Override
    public ResponseResult register(User user) {
        String password = user.getPassword();
        if(null != password && null != user.getPhoneNumber()){
            // 对密码进行加密
            password =  passwordEncoder.encode(password);
            user.setPassword(password);
            // 存入数据库
            userMapper.insert(user);
        }else {
            return new ResponseResult(409,"缺少关键字");
        }
        return new ResponseResult(200,"注册成功");
    }
}
